package org.myOrg.spetrum.combination;

import java.util.ArrayList;
import java.util.List;

/**
 * 
 * any tuple paramIndex is from big to small
 * 
 * @author XinTao Niu
 * 
 */
public class TupleImplement implements Tuple {

	private int[] paramIndex;
	private int[] paramValue;
	private int degree;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#toString(int)
	 */
	@Override
	public String toString(int length) {

		int[] data = new int[length];
		for (int i = 0; i < length; i++) {
			data[i] = -1;
		}
		for (int i = 0; i < degree; i++) {
			data[paramIndex[i]] = paramValue[i];
		}

		String rs = "";
		rs += "(";
		for (int i = 0; i < length; i++) {
			if (data[i] == -1)
				rs += " - ";
			else
				rs += " " + data[i] + " ";
			if (i != length - 1)
				rs += ",";
		}
		rs += ")";
		return rs;
	}

	public TupleImplement(int degree) {
		paramIndex = new int[degree];
		paramValue = new int[degree];
		this.degree = degree;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object tuple) {
		if (!(tuple instanceof Tuple))
			return false;

		if (this.degree == ((Tuple) tuple).getDegree()) {
			for (int i = 0; i < degree; i++) {
				if (paramIndex[i] != ((Tuple) tuple).getParamIndex()[i]
						|| paramValue[i] != ((Tuple) tuple).getParamValue()[i])
					return false;
			}
			return true;
		} else
			return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#hashCode()
	 */
	@Override
	public int hashCode() {
		String string = "";
		for (int i : this.paramIndex) {
			string += i;
		}
		for (int i : this.paramValue) {
			string += i;
		}
		return string.hashCode();

	}

	@Override
	public Tuple copy() {
		Tuple tuple = new TupleImplement(this.degree);
		for (int i = 0; i < this.degree; i++) {
			tuple.set(i, this.paramIndex[i], this.paramValue[i]);
		}
		return tuple;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#set(int, int, int)
	 */
	@Override
	public void set(int location, int index, int value) {
		paramIndex[location] = index;
		paramValue[location] = value;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#getParamIndex()
	 */
	@Override
	public int[] getParamIndex() {
		return paramIndex;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#setParamIndex(int[])
	 */
	@Override
	public void setParamIndex(int[] paramIndex) {
		this.paramIndex = paramIndex;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#getParamValue()
	 */
	@Override
	public int[] getParamValue() {
		return paramValue;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#setParamValue(int[])
	 */
	@Override
	public void setParamValue(int[] paramValue) {
		this.paramValue = paramValue;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#setDegree(int)
	 */
	@Override
	public void setDegree(int degree) {
		this.degree = degree;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#getDegree()
	 */
	@Override
	public int getDegree() {
		return degree;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.myOrg.spetrum.combination.Tuple#getChildTuples()
	 */
	@Override
	public List<Tuple> getChildTuples() {
		// TODO Auto-generated method stub
		List<Tuple> childs = new ArrayList<Tuple>();
		for (int i = 0; i < this.degree; i++) {
			Tuple tuple = getChild(i);
			if (tuple != null)
				childs.add(tuple);
		}

		return childs;
	}

	/**
	 * @param i
	 * @return the ith child of this tuple
	 */
	private Tuple getChild(int i) {

		if (this.degree == 1)
			return null;

		Tuple tuple = new TupleImplement(this.degree - 1);
		int index = 0;
		for (int j = 0; j < this.degree; j++) {
			if (i != this.degree - 1 - j) {
				tuple.set(index++, this.paramIndex[j], this.paramValue[j]);
			}
		}
		return tuple;
	}

	@Override
	public boolean contains(Tuple tuple) {
		// TODO Auto-generated method stub
		if (this.degree < tuple.getDegree())
			return false;
		else {
			for (int i = 0; i < tuple.getDegree(); i++) {
				if (!hasElement(tuple, i)) {
					return false;
				}
			}
			return true;

		}
	}

	private boolean hasElement(Tuple tuple, int i) {
		for (int j = 0; j < this.degree; j++) {
			if (this.getParamIndex()[j] == tuple.getParamIndex()[i]
					&& this.getParamValue()[j] == tuple.getParamValue()[i]) {
				return true;
			}
		}
		return false;
	}

}
